package application;


import java.util.HashMap;
import java.util.Vector;


import namingService.AMI_ClientHandler;
import namingService.AMI_ServerHandler;
import namingService.Client;
import namingService.ClientHelper;
import namingService.Server;
import namingService.ServerHelper;
import namingService.ServerPOA;
import namingService._ClientStub;
import namingService._ServerStub;

import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;



public class DirectoryServer extends ServerPOA {
	
	private Vector<EntityNaming> LocationRecord = null;
	private HashMap<String, Integer> IndexName = null;
	private static Server father = null;
	private static ORB orb = null;
	private static AMI_ServerHandler sh = null;
	private static AMI_ClientHandler ch = null;

	public DirectoryServer(){
		LocationRecord = new Vector<EntityNaming>();
		IndexName = new HashMap<String, Integer>();
	}
	
	public synchronized void insertEntity(String name, String address) {
		
		System.out.println("Richiesta di inserimento "+name);
		
		EntityNaming e = new EntityNaming(name, address);
		
		if (father != null && IndexName.get(name) == null){
			((_ServerStub) father).sendc_insertEntity(sh, name, orb.object_to_string(_this()));
			IndexName.put(name, new Integer(0));
		}
		
		if (IndexName.get(name)==null){
			IndexName.put(name, new Integer(0));
		}
		IndexName.put(name, IndexName.get(name)+1);
		LocationRecord.add(e);
		
	}

	public synchronized void removeEntity(String name, String address) {
		
		System.out.println("Richiesta di rimozione "+name);
		
		EntityNaming e = new EntityNaming(name,address);
		if (IndexName.get(name)!=null){
			if (father != null && IndexName.get(name) < 2){
				((_ServerStub) father).sendc_removeEntity(sh, name,orb.object_to_string(_this()));
			}
			
			if (IndexName.get(name) == 1){
				IndexName.remove(name);
			} else {
				IndexName.put(name, IndexName.get(name)-1);
			}
			
			
			LocationRecord.remove(e);
			
			
		}
		
	}

	public synchronized void searchEntity(String name, String requester) {
		System.out.println("Richiesta di ricerca "+name);
		if (IndexName.get(name)!=null){	
			for (int i =0 ; i < LocationRecord.size();i++){
				if (LocationRecord.get(i).getName().equals(name)){
					org.omg.CORBA.Object obj = orb.string_to_object(LocationRecord.get(i).getHost());
					Server ser = ServerHelper.narrow(obj);
					((_ServerStub)ser).sendc_searchEntity(sh, name, requester);
				}
			}
		} else {
			if (father != null){
				((_ServerStub) father).sendc_searchEntity(sh, name, requester);
			} else {
				org.omg.CORBA.Object obj = orb.string_to_object(requester);
				Client cli = ClientHelper.narrow(obj);
				((_ClientStub)cli).sendc_messageToClient(ch,"ENTITA' NON PRESENTE");
			}
			
		}
	}
	
	private void setAttributes(ORB orb2, Server father2, AMI_ServerHandler sh2,
			AMI_ClientHandler ch2) {
	
		orb = orb2;
		father = father2;
		sh = sh2;
		ch = ch2;
	}

	public static void main(String[] args) {

			try {
				
				DirectoryServer dn = new DirectoryServer();

				String orbconf[] = { args[0], args[1], args[2], args[3] };
				orb = ORB.init(orbconf, null);
				POA rootPOA = POAHelper.narrow(orb
						.resolve_initial_references("RootPOA"));
				rootPOA.the_POAManager().activate();
				org.omg.CORBA.Object Lref = rootPOA.servant_to_reference(dn);

				Object objRef = orb.resolve_initial_references("NameService");
				NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

				NameComponent pathDir[] = ncRef.to_name("Servers/DirectoryServers/"+ args[4]);
				ncRef.rebind(pathDir, Lref);
				System.out.println(args[4] + " added...");
				
				ch = new AMI_ClientHandlerImpl()._this(orb);
				
				if(args.length>5){
					NameComponent fatherN[] = ncRef.to_name("Servers/DirectoryServers/"+ args[5]);
					org.omg.CORBA.Object fatherObj;

				fatherObj = ncRef.resolve(fatherN);
				father =  namingService.ServerHelper.narrow(fatherObj);
				sh = new AMI_ServerHandlerImpl()._this(orb);
				dn.setAttributes(orb,father,sh,ch);
				
				}

			orb.run();

			} catch (NotFound e) {
				e.printStackTrace();
				System.exit(1);
			} catch (Exception e) {
				e.printStackTrace();
				System.exit(1);
			}
			
	}


}